<template>
  <div>
    <div style="display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:12px">
      <div>
        <!-- Wrap controls in a form so pressing Enter submits reliably from the inner native input -->
        <!-- 自动触发搜索：输入 >=2 个字符后会经过防抖自动搜索；移除显式搜索按钮 -->
        <form @submit.prevent="applyFilters" style="display:flex; align-items:center; gap:8px">
          <el-input v-model="q" placeholder="请输入日志关键字搜索（message/ip/location/tp）" clearable @clear="onClearQ" @keydown.enter="applyFilters" style="width:420px" />
          <!-- Apply filter immediately when user selection changes -->
          <el-select v-model.number="userFilter" placeholder="筛选用户" clearable @change="applyFilters" style="width:220px">
            <el-option v-for="u in usersForFilter" :key="u.id" :label="u.user_name" :value="u.id" />
          </el-select>
        </form>
        <!-- 已移除筛选按钮，选择用户后自动过滤 -->
      </div>
    </div>

    <el-table :data="logs" stripe border style="width:100%" remote @sort-change="onSortChange" @header-click="onHeaderClick">
      <el-table-column label="序号" width="70">
        <template #default="{ $index }">{{ (page - 1) * pageSize + $index + 1 }}</template>
      </el-table-column>
      <el-table-column prop="time_stamp" label="时间" sortable>
        <template #default="{ row }">{{ formatDate(row.time_stamp) }}</template>
      </el-table-column>
      <el-table-column prop="message" label="信息" />
      <el-table-column prop="user_name" label="用户" sortable />
      <el-table-column prop="ip" label="IP" sortable />
      <el-table-column prop="location" label="地点" />
      <el-table-column prop="tp" label="类别" />
      <el-table-column label="对象" width="80">
        <template #default="{ row }">
          <el-button type="text" size="small" @click="viewJson(row)">查看</el-button>
        </template>
      </el-table-column>
    </el-table>

    <div style="margin-top:12px; display:flex; justify-content:flex-end; align-items:center">
      <el-pagination
        background
        layout="total, sizes, prev, pager, next"
        :current-page="page"
        :page-size="pageSize"
        :page-sizes="[10,20,50]"
        :total="total"
        @current-change="gotoPage"
        @size-change="onSizeChange"
      />
    </div>

    <el-alert v-if="error" type="error" :title="error" show-icon style="margin-top:12px" />

    <el-dialog title="对象内容" v-model="showJson" width="720px">
      <pre style="white-space:pre-wrap; word-break:break-word">{{ selectedJson }}</pre>
      <template #footer>
        <el-button @click="showJson = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import { useAuthStore } from '../stores/auth'

const auth = useAuthStore()
const logs = ref<any[]>([])
const usersForFilter = ref<any[]>([])
const error = ref('')

const q = ref('')
const userFilter = ref<number | null>(null)

const page = ref(1)
const pageSize = ref(10)
const total = ref(0)

const sortBy = ref<string | null>(null)
const sortOrder = ref<'asc'|'desc'|null>(null)

const showJson = ref(false)
const selectedJson = ref('')

function formatDate(s: string) {
  if (!s) return ''
  try {
    const d = new Date(s)
    return d.toLocaleString()
  } catch { return s }
}

async function loadUsersForFilter() {
  try {
    const res = await auth.apiFetch('/users?limit=1000000')
    // backend returns { users: [...], total }
    usersForFilter.value = (res.users || res || []).map((u: any) => ({ id: u.id, user_name: u.user_name || u.alisa || ('uid:' + u.id) }))
  } catch (e) {
    usersForFilter.value = []
  }
}

async function load() {
  error.value = ''
  try {
    const params = new URLSearchParams()
    params.set('page', String(page.value))
    params.set('limit', String(pageSize.value))
    if (sortBy.value) params.set('sort_by', sortBy.value)
    if (sortOrder.value) params.set('sort_order', sortOrder.value)
    if (q.value && String(q.value).trim() !== '') params.set('q', String(q.value).trim())
    if (userFilter.value) params.set('user_id', String(userFilter.value))

    // debug: log what we are sending to backend
    console.debug('[LogList] loading logs with params:', params.toString(), 'q=', q.value)

    const res = await auth.apiFetch(`/logs?${params.toString()}`)
    logs.value = (res.logs || res || [])
    total.value = typeof res.total === 'number' ? res.total : logs.value.length
  } catch (e: any) {
    error.value = '加载日志失败'
    ElMessage.error(error.value)
  }
}

onMounted(async () => {
  await loadUsersForFilter()
  await load()
})

// debounce timer id for auto-search
let searchTimer: number | null = null

// Auto-search when user types 2 or more characters (debounced)
watch(q, (val) => {
  if (searchTimer) {
    clearTimeout(searchTimer)
    searchTimer = null
  }
  const s = String(val || '').trim()
  if (s === '') {
    // empty -> apply filters to reset list
    applyFilters()
    return
  }
  if (s.length >= 2) {
    // debounce 350ms
    searchTimer = window.setTimeout(() => {
      applyFilters()
      searchTimer = null
    }, 350)
  }
}, { immediate: false })

onUnmounted(() => {
  if (searchTimer) {
    clearTimeout(searchTimer)
    searchTimer = null
  }
})

function applyFilters() {
  page.value = 1
  load()
}

function onClearQ() {
  q.value = ''
  applyFilters()
}

function gotoPage(n: number) {
  if (n < 1) n = 1
  page.value = n
  load()
}

function onSizeChange(size: number) {
  pageSize.value = size
  gotoPage(1)
}

function viewJson(row: any) {
  selectedJson.value = row.obj_json ? (typeof row.obj_json === 'string' ? row.obj_json : JSON.stringify(row.obj_json, null, 2)) : '(无)'
  showJson.value = true
}

function onSortChange(sort: any) {
  const prop = sort && sort.prop ? sort.prop : (sort && sort.column ? (sort.column.property ?? sort.column.prop ?? null) : null)
  const orderRaw = sort && sort.order ? sort.order : null
  let order: string | null = null
  if (orderRaw) {
    order = (orderRaw === 'ascending' || orderRaw === 'asc') ? 'asc' : 'desc'
  } else if (prop && prop === sortBy.value) {
    if (sortOrder.value === 'asc') order = 'desc'
    else if (sortOrder.value === 'desc') order = null
    else order = 'asc'
  }

  if (!prop || !order) {
    sortBy.value = null
    sortOrder.value = null
  } else {
    sortBy.value = String(prop)
    sortOrder.value = order as 'asc'|'desc'
  }
  page.value = 1
  load()
}

function onHeaderClick(column: any) {
  if (!column) return
  const prop = column.property ?? column.prop ?? null
  if (!prop) return
  if (!column.sortable && column.sortable !== 'custom' && column.sortable !== true) return
  if (sortBy.value !== prop) {
    sortBy.value = String(prop)
    sortOrder.value = 'asc'
  } else {
    if (sortOrder.value === 'asc') sortOrder.value = 'desc'
    else if (sortOrder.value === 'desc') { sortBy.value = null; sortOrder.value = null }
    else sortOrder.value = 'asc'
  }
  page.value = 1
  load()
}
</script>

<style scoped>
</style>
